package com.lou1052.kryo;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.*;
import com.lou1052.core.base.annotation.thread.NotThreadSafe;
import com.lou1052.core.constant.tlocal.ThreadLocalKryo;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;

/**
 * Created with IntelliJ IDEA.
 * User: liuqing
 * Date: 2015/11/2
 * Time: 21:01
 * To change this template use File | Settings | File Templates.
 */
@NotThreadSafe
public class KryoExt extends Kryo {

    private static final int bufferSize = 4096;//4k

    private static final int maxBufferSize = 1048576;//1m

    public Object readClassAndObject(byte[] inputByte) {
        if(inputByte==null){
            return null;
        }
        try (Input input = new Input(inputByte)){
            return super.readClassAndObject(input);
        }
    }

    public Object readClassAndObject(InputStream inputStream) {
        if(inputStream==null){
            return null;
        }
        try (Input input = new Input(inputStream)){
            return super.readClassAndObject(input);
        }
    }

    public <T> T readObject(byte[] inputByte, Class<T> type) {
        if(inputByte==null){
            return null;
        }
        try (Input input = new Input(inputByte)) {
            return super.readObject(input, type);
        }
    }

    public <T> T readObject(InputStream inputStream, Class<T> type) {
        if(inputStream==null){
            return null;
        }
        try (Input input = new Input(inputStream)) {
            return super.readObject(input, type);
        }
    }


    public <T> T readObjectOrNull(byte[] inputByte, Class<T> type) {
        if(inputByte==null){
            return null;
        }
        try (Input input = new Input(inputByte)) {
            return super.readObjectOrNull(input, type);
        }
    }

    public <T> T readObjectOrNull(InputStream inputStream, Class<T> type) {
        if(inputStream==null){
            return null;
        }
        try (Input input = new Input(inputStream)) {
            return super.readObjectOrNull(input, type);
        }
    }


    public byte[] writeClassAndObject(Object object) {
        try(Output output = new Output(bufferSize,maxBufferSize)) {
            super.writeClassAndObject(output, object);
            return output.toBytes();
        }
    }

    public void writeClassAndObject(OutputStream outputStream, Object object) {
        try(Output output = new Output(outputStream)) {
            super.writeClassAndObject(output, object);
        }
    }

    public byte[] writeObject(Object object) {
        try(Output output = new Output(bufferSize,maxBufferSize)) {
            super.writeObject(output, object);
            return output.toBytes();
        }
    }

    public void writeObject(OutputStream outputStream, Object object) {
        try(Output output = new Output(outputStream)) {
            super.writeObject(output, object);
        }
    }



    public byte[] writeObjectOrNull(Object object, Class type) {
        try(Output output = new Output(bufferSize,maxBufferSize)) {
            super.writeObjectOrNull(output, object, type);
            return output.toBytes();
        }
    }

    public void writeObjectOrNull(OutputStream outputStream, Object object, Class type) {
        try(Output output = new Output(outputStream)) {
            super.writeObjectOrNull(output, object, type);
        }
    }

    //unsafe fast
    public Object unsafeReadClassAndObject(byte[] inputByte) {
        if(inputByte==null){
            return null;
        }
        try (UnsafeInput input = new UnsafeInput(inputByte)){
            return super.readClassAndObject(input);
        }
    }

    public Object unsafeReadClassAndObject(InputStream inputStream) {
        if(inputStream==null){
            return null;
        }
        try (UnsafeInput input = new UnsafeInput(inputStream)){
            return super.readClassAndObject(input);
        }
    }

    public <T> T unsafeReadObject(byte[] inputByte, Class<T> type) {
        if(inputByte==null){
            return null;
        }
        try (UnsafeInput input = new UnsafeInput(inputByte)) {
            return super.readObject(input, type);
        }
    }

    public <T> T unsafeReadObject(InputStream inputStream, Class<T> type) {
        if(inputStream==null){
            return null;
        }
        try (UnsafeInput input = new UnsafeInput(inputStream)) {
            return super.readObject(input, type);
        }
    }


    public <T> T unsafeReadObjectOrNull(byte[] inputByte, Class<T> type) {
        if(inputByte==null){
            return null;
        }
        try (UnsafeInput input = new UnsafeInput(inputByte)) {
            return super.readObjectOrNull(input, type);
        }
    }

    public <T> T unsafeReadObjectOrNull(InputStream inputStream, Class<T> type) {
        if(inputStream==null){
            return null;
        }
        try (UnsafeInput input = new UnsafeInput(inputStream)) {
            return super.readObjectOrNull(input, type);
        }
    }


    public byte[] unsafeWriteClassAndObject(Object object) {
        try(Output output = new UnsafeOutput(bufferSize,maxBufferSize*2)) {
            super.writeClassAndObject(output, object);
            return output.toBytes();
        }
    }

    public void unsafeWriteClassAndObject(OutputStream outputStream, Object object) {
        try(UnsafeOutput output = new UnsafeOutput(outputStream)) {
            super.writeClassAndObject(output, object);
        }
    }

    public byte[] unsafeWriteObject(Object object) {
        try(UnsafeMemoryOutput output = new UnsafeMemoryOutput(bufferSize,maxBufferSize*2)) {
            super.writeObject(output, object);
            return output.toBytes();
        }
    }

    public void unsafeWriteObject(OutputStream outputStream, Object object) {
        try(UnsafeMemoryOutput output = new UnsafeMemoryOutput(outputStream)) {
            super.writeObject(output, object);
        }
    }

    public byte[] unsafeWriteObjectOrNull(Object object, Class type) {
        try(UnsafeMemoryOutput output = new UnsafeMemoryOutput(bufferSize,maxBufferSize*2)) {
            super.writeObjectOrNull(output, object, type);
            return output.toBytes();
        }
    }

    public void unsafeWriteObjectOrNull(OutputStream outputStream, Object object, Class type) {
        try(UnsafeMemoryOutput output = new UnsafeMemoryOutput(outputStream)) {
            super.writeObjectOrNull(output, object, type);
        }
    }
}
